/*
 * Acceptor.java    0.0.1    22/set/2009
 * 
 * Copyright (c) 2009 mentalsmash.org
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * The use of the Apache License does not indicate that this project is
 * affiliated with the Apache Software Foundation.
 */ 
package org.mentalsmash.tazio.net.cs.server.impl;

import org.mentalsmash.tazio.net.cs.CSSubsystemException;


/**
 * The Acceptor has the role to monitor source of connection (e.g. ServerSockets), accept them if it is
 * the case, and eventually register the established connections on an associated Dispatcher.
 * <p>
 * It could be implemented as a stand-alone thread or it could be run by a pre-existing thread,
 * depending on implementations.
 * </p>
 * @version    0.0.1    22/set/2009    
 * @author     Andrea Reale <andrea.reale@gmail.com>
 */
public interface Acceptor {

	
	/**
	 * Start a thread that runs the acceptor.
	 * <p>
	 * From this moment on, the acceptor will listen to incoming connection
	 * on the specified source, accept them, and then pass them to the given dispatcher.
	 * </p>
	 * @return a reference to the Thread that is running the acceptor. It is not guaranteed
	 *         that the thread running the acceptor will remain the same  throughout the lyfe
	 *         of the program. It could change due to an acceptor restart. 
	 */
	Thread start();
	
	/**
	 * Stops the thread running the acceptor
	 * <p>
	 * No more connections will be accepted after this method returns. Readiness events on pre-existing
	 * connections will continue to be dispatched, until the dispatcher is stopped.
	 * </p>
	 */
	void stop();
	
	/**
	 * Sets the dispatcher to be used by the acceptor when new connections are accepted.
	 * <p>
	 * This method <strong>must</strong> be called while the acceptor thread is not running,
	 * i.e. before calling {@link Acceptor#start() start()}. Otherwise a 
	 * {@link CSSubsystemException NetworkException} is thrown.
	 * </p>
	 * <p>
	 * You can check whether the acceptor is running calling {Acceptor#isRunning() isRunning()}.
	 * </p>
	 * @param dispatcher an instance of {@link Dispatcher Dispatcher}.
	 * @throws CSSubsystemException thrown if this method is called while the acceptor is running
	 */
	void setDispatcher(Dispatcher dispatcher) throws CSSubsystemException;
	
	/**
	 * Returns the dispatcher associated to the acceptor.
	 * <p> 
	 * If the acceptor is running 
	 * that dispatcher will be used to manage readiness events on established connections.
	 * </p>
	 * @return the dispatcher associated to the acceptor
	 */
	Dispatcher getCurrentDispatcher();
	
	/**
	 * Checks whether the Acceptor Thread is currently running.
	 * <p>
	 * Use this method when you want to change any parameter of the acceptor that cannot
	 * be modified while it is running (e.g. {@link Acceptor#setDispatcher(Dispatcher) setDispatcher()})
	 * </p>
	 * @return true if the acceptor thread is currently running
	 */
	boolean isRunning();
	
	/**
	 * Register a lister on the acceptor. Appropriate methods of registered listeners will be
	 * invoked upon interesting events occurrences.
	 * @param listener an instance of AcceptorListener
	 * @return true if the registration is successful 
	 */
	boolean registerListener(AcceptorListener listener);
	/**
	 * Removes a listener from the listeners which are registered on the acceptor. If the
	 * listener was not previously registered on the acceptor nothing is done.
	 * @param listener a reference to the listener to remove
	 * @return true if the listener was found and removed, false if the listener was not registered.
	 */
	boolean removeListener(AcceptorListener listener);
	
}
